package com.way.token.mobile;

import cn.hutool.core.bean.BeanUtil;
import com.way.pojo.User;
import com.way.service.MobileUserService;
import com.way.token.exception.UserNotFoundException;
import lombok.Data;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.util.StringUtils;

/**
 * 自定义手机模式的提供者
 * 判断token类型是否为MobileCodeAuthenticationToken,如果是则会使用此provider
 *
 * @author: 魏彪
 */
@Data
public class MobileCodeAuthenticationProvider implements AuthenticationProvider, MessageSourceAware {

    private MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();

    @Override
    public void setMessageSource(MessageSource messageSource) {
        this.messages = new MessageSourceAccessor(messageSource);
    }

    /**
     * userDetailsService的实现类 不需要自动注入 直接传入
     */
    private MobileUserService mobileUserService;

    /**
     * 业务处理的方法
     *
     * @param authentication
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // 未认证之前是手机号 认证之后是客户信息
        String principal = (String) authentication.getPrincipal();
        if (StringUtils.isEmpty(principal)) {
            throw new BadCredentialsException("手机号不能为空");
        }

        UserDetails user;
        try {
            User bean = BeanUtil.toBean(authentication.getDetails(), User.class);
            user = mobileUserService.loadByWechat(bean);
        } catch (UsernameNotFoundException var6) {
            throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "查询用户信息失败!"));
        }
        check(user);
        MobileCodeAuthenticationToken authenticationToken = new MobileCodeAuthenticationToken(user, user.getAuthorities());
        authenticationToken.setDetails(authenticationToken.getDetails());
        return authenticationToken;
    }

    /**
     * 账号禁用、锁定、超时校验
     *
     * @param user
     */
    private void check(UserDetails user) {
        if (user == null) {
            throw new UserNotFoundException(this.messages.getMessage("未查询到用户", "未查询到用户"));
        }
        if (!user.isAccountNonLocked()) {
            throw new LockedException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.locked", "User account is locked"));
        } else if (!user.isEnabled()) {
            throw new DisabledException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.disabled", "User is disabled"));
        } else if (!user.isAccountNonExpired()) {
            throw new AccountExpiredException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.expired", "User account has expired"));
        }
    }

    /**
     * 判断是否为MobileCodeAuthenticationToken类型  如果是 直接调用 切断过滤器链
     * 如果不是 继续查找
     *
     * @param authentication
     * @return
     */
    @Override
    public boolean supports(Class<?> authentication) {
        return MobileCodeAuthenticationToken.class.isAssignableFrom(authentication);
    }

}
